package jdbc;

import org.junit.jupiter.api.Test;

import java.sql.*;

/**
 * 事务
 */
public class Transaction_ {

    public static void main(String[] args) {

        /*
            1.JDBC程序中当一个Connection对象创建时，默认情况下是自动提交事务：
            每次执行一个SQL语句时，如果执行成功，就会向数据库自动提交，而不能回滚。
            2.JDBC程序中为了让多个SQL语句作为一个整体执行，需要使用事务
            3.调用 Connection 的 setAutoCommit(false)可以取消自动提交事务
            4.在所有的SQL语句都成功执行后，调用Connection的commit()方法提交事务
            5.在其中某个操作失败或出现异常时，调用rollback()方法回滚事务
         */



    }

    //没有使用事务
    @Test
    public void noTransaction() {
        //操作转账业务
        //1.得到连接
        Connection connection = null;
        //2.组织sql语句
        String sql = "update account set money = money - 100 where id = ?";
        String sql2 = "update account set money = money + 100 where id = ?";
        //3.创建PreparedStatement对象
        PreparedStatement preparedStatement = null;
        PreparedStatement preparedStatement2 = null;
        try {
            connection = JDBCUtils.getConnection(); //默认情况下 Connection对象时默认自动提交
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setInt(1, 1);
            int rows = preparedStatement.executeUpdate();
            //这里抛出异常，只执行成功第一条sql语句
            int i = 1 / 0;
            preparedStatement2 = connection.prepareStatement(sql2);
            preparedStatement.setInt(1, 2);
            int rows2 = preparedStatement2.executeUpdate();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //4.关闭资源
            JDBCUtils.close(null, preparedStatement, connection);
        }
    }

    //使用事务解决
    @Test
    public void useTransaction() {
        //操作转账业务
        //1.得到连接
        Connection connection = null;
        //2.组织sql语句
        String sql = "update account set money = money - 100 where id = ?";
        String sql2 = "update account set money = money + 100 where id = ?";
        //3.创建PreparedStatement对象
        PreparedStatement preparedStatement = null;
        PreparedStatement preparedStatement2 = null;
        try {
            connection = JDBCUtils.getConnection(); //默认情况下 Connection对象时默认自动提交
            //将connection设置为不自动提交
            connection.setAutoCommit(false);    //开启事务
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setInt(1, 1);
            int rows = preparedStatement.executeUpdate();
            //这里抛出异常，只执行成功第一条sql语句
            int i = 1 / 0;
            preparedStatement2 = connection.prepareStatement(sql2);
            preparedStatement.setInt(1, 2);
            int rows2 = preparedStatement2.executeUpdate();
            //提交事务
            connection.commit();
        } catch (Exception e) {
            //这里可以进行回滚，撤销执行的sql
            //默认回滚到事务开始的状态
            System.out.println("执行发生了异常，撤销执行的sql");
            try {
                connection.rollback();
            } catch (SQLException ex) {
                e.printStackTrace();
            }
            e.printStackTrace();
        } finally {
            //4.关闭资源
            JDBCUtils.close(null, preparedStatement, connection);
        }
    }
}
